//TODO: guard
//TODO: text extern "C" with function overloading
//TODO: decorate the MACRO names with Namespaces prefixes

//#include <boost/preprocessor/cat.hpp>
#include "for_each_with_separator.hpp"


#define ACTION_PARAMETERS_LIST(SEQ) 			jnipp::from_java(env, BOOST_PP_TUPLE_ELEM(2,1, BOOST_PP_SEQ_HEAD(SEQ)) )
#define ACTION_PARAMETERS_LIST_SIGNATURE(SEQ) 	BOOST_PP_TUPLE_ELEM(2,0, BOOST_PP_SEQ_HEAD(SEQ)) BOOST_PP_TUPLE_ELEM(2,1, BOOST_PP_SEQ_HEAD(SEQ))

#define PARAMETERS_LIST(PARAM_SEQ) 				FOR_EACH_WITH_SEPARATOR( PARAM_SEQ, ACTION_PARAMETERS_LIST )
#define PARAMETERS_LIST_SIGNATURE(PARAM_SEQ)	FOR_EACH_WITH_SEPARATOR( PARAM_SEQ, ACTION_PARAMETERS_LIST_SIGNATURE )

#define JNI_FUNCTION_FILLER_0(X, Y)                                \
	((X, Y)) JNI_FUNCTION_FILLER_1
#define JNI_FUNCTION_FILLER_1(X, Y)                                \
	((X, Y)) JNI_FUNCTION_FILLER_0
#define JNI_FUNCTION_FILLER_0_END
#define JNI_FUNCTION_FILLER_1_END

#define JNI_FUNCTION_FILLER(ATTRIBUTES) BOOST_PP_CAT( JNI_FUNCTION_FILLER_0 ATTRIBUTES,_END)

#define JNI_FUNCTION_DETAIL(PACKAGE_NAME, CLASS_NAME, FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, PARAM_SEQ)	\
	extern "C"																										\
	RETURN_TYPE Java_ ## PACKAGE_NAME ## _ ## CLASS_NAME ## _ ## FUNCTION_NAME 										\
		( JNIEnv * env, jobject obj, PARAMETERS_LIST_SIGNATURE(PARAM_SEQ) )											\
	{																												\
		return NATIVE_FUNCTION_NAME(																				\
			PARAMETERS_LIST(PARAM_SEQ)																				\
		);																											\
	}
/**/


#define JNI_FUNCTION(PACKAGE_NAME, CLASS_NAME, FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, PARAM_SEQ)			\
	JNI_FUNCTION_DETAIL(PACKAGE_NAME, CLASS_NAME, FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, JNI_FUNCTION_FILLER(PARAM_SEQ))
/**/


//#define JNI_FUNCTION(PACKAGE_NAME, CLASS_NAME, FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, PARAMETER_TYPE1, PARAMETER_NAME1)\
//			extern "C"\
//			RETURN_TYPE Java_ ## PACKAGE_NAME ## _ ## CLASS_NAME ## _ ## FUNCTION_NAME \
//			( JNIEnv * env, jobject obj, PARAMETER_TYPE1 PARAMETER_NAME1 )\
//			{\
//				return NATIVE_FUNCTION_NAME(\
//					jnipp::from_java(env, PARAMETER_NAME1 )\
//				);\
//			}
